// Thud - a dynamic object-oriented language
// Copyright (C) 2009,2010 David H. Hovemeyer <david.hovemeyer@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/*
 * Opcode.cpp
 *
 *  Created on: Dec 6 2009
 *      Author: dhovemey
 */

#include <cassert>
#include "vm/Opcode.h"

#define I OP_FLAG_I8_CONST
#define C OP_FLAG_CP_REF
#define B OP_FLAG_BRANCH

static const int s_opcodeFlags[] = {
		0,      // OP_NOP
		C,      // OP_NEW
		0,      // OP_DUP
		C,      // OP_PUSH_CONST
		I,      // OP_PUSH_I8_CONST
		I|C,    // OP_CALL
		I,      // OP_LOAD_LOCAL
		I,      // OP_STORE_LOCAL
		C,      // OP_LOAD_FIELD
		C,      // OP_STORE_FIELD
		0,      // OP_POP
		B,      // OP_GOTO
		B,      // OP_IFTRUE
		B,      // OP_IFFALSE
		0,      // OP_PUSH_NIL
		0,      // OP_RETURN
		C,      // OP_PUSH_MODULE_REF
};

static const wchar_t * const s_opcodeNames[] = {
		L"nop",               // OP_NOP
		L"new",               // OP_NEW
		L"dup",               // OP_DUP
		L"push_const",        // OP_PUSH_CONST
		L"push_i8_const",     // OP_PUSH_I8_CONST
		L"call",              // OP_CALL
		L"load_local",        // OP_LOAD_LOCAL
		L"store_local",       // OP_STORE_LOCAL
		L"load_field",        // OP_LOAD_FIELD
		L"store_field",       // OP_STORE_FIELD
		L"pop",               // OP_POP
		L"goto",              // OP_GOTO
		L"iftrue",            // OP_IFTRUE
		L"iffalse",           // OP_IFFALSE
		L"push_nil",          // OP_PUSH_NIL
		L"return",            // OP_RETURN
		L"push_module_ref",   // OP_PUSH_MODULE_REF
};

int opcodeGetFlags(Opcode opcode)
{
	assert(opcode >= 0 && opcode < OP_NUM_OPCODES);
	return s_opcodeFlags[opcode];
}

const wchar_t *opcodeGetName(Opcode opcode)
{
	assert(opcode >= 0 && opcode < OP_NUM_OPCODES);
	return s_opcodeNames[opcode];
}
